#pragma once
#include <ntddk.h>
#include "HandleBase.h"
#include "allocator.h"
#include "X86_Defination.h"
#define GPREGISTER_NUM 8

typedef struct _InterruptContext//No ErrorCode
{
	UINT32 EDI;
	UINT32 ESI;
	UINT32 EBP;
	UINT32 ESP;
	UINT32 EBX;
	UINT32 EDX;
	UINT32 ECX;
	UINT32 EAX;
	UINT32 CurrentEflags;
	UINT32 EIP;
	UINT32 CS;
	UINT32 EFLAGS;
}InterruptContext, *PINTERRUPT_CONTEXT, **PPINTERRUPT_CONTEXT;

typedef bool (_cdecl * InterruptRoutine)(InterruptContext);

class X86_InterruptMgr;
class InterruptObj
{
	friend class X86_InterruptMgr;
	InterruptRoutine _routine;
	void* _context;
	DELCARE_SUPPORT_ALLOCATOR
};

class InterruptHandle
{
	friend class X86_InterruptMgr;

	//InterruptObj* pInterruptObj;
	unsigned id;
	bool bOpened;

	InterruptHandle(unsigned targetId) : id(targetId),bOpened(true){}
public:
	InterruptHandle() : bOpened(false){}
	bool IsOpened()const{return bOpened;}
	~InterruptHandle(){bOpened = false;}
};

class X86_InterruptMgr
{
	friend class InterruptHandle;
	
	DELCARE_SUPPORT_ALLOCATOR
	static X86_InterruptMgr* _instance;

	X86_InterruptMgr(void);
	~X86_InterruptMgr(void);

public:

	static X86_InterruptMgr* Instance();
	static PGATE GetInterruptDesc(unsigned id);
	static void* GetInterruptAddress(unsigned id);
	static GATE SetInterruptAddress(unsigned id, void* address);

	InterruptHandle RegisterInterrupt(ULONG id, InterruptRoutine routine, void* context);
	void UnRegisterInterrupt(InterruptHandle);
};
